#!/usr/local/bin/python2.7
#-*- python -*-
# Simple (VIC20) serial program uploader
# Based on scripts I've been hacking on for over a decade..
# ---
# Copyright 2013 Chris Baird,, <cjb@brushtail.apana.org.au>
# Distributed to the GPLV3 terms and conditions.

recordwidth = 20 # for the BASIC bootloader
#recordwidth = 80 # for the machinecode bootloader
startaddr = -1
randomerror = 0

import sys
import time
import string
import random

from serial import *

ser = Serial()
ser.setPort("/dev/ttyU0")       # modify this!
ser.setStopbits(1)
ser.setParity('N')
ser.setBaudrate(1200)           # the limit of the kernal rs232 code
ser.timeout=0.1
ser.open()


def binarystr_to_paperfmt(startaddr,binstring):
    str = "%05d" % startaddr
    chksum = 0
    for ch in list(binstring):
        str = str + "%3d" % ord(ch)
        chksum += ord(ch)
    str = str + "%3d" % (chksum & 255)
    return str


def file_to_paperfmt(addr,myfile):
    try:
        inputfile = open(myfile,"r")
    except:
        exit("input file: couldn't open file for reading")

    hexrecords = []
    while 1:
        if addr == 0:
            lo = ord(inputfile.read(1))
            hi = ord(inputfile.read(1))
            addr = lo + (256 * hi)
            print "Starting address: ",addr

        somebytes = inputfile.read(recordwidth)
        if len(somebytes) == 0:
            break
        b = binarystr_to_paperfmt(addr,somebytes)
        #print b
        hexrecords = hexrecords + [b]
        if len(somebytes) < recordwidth:
            break
        addr = addr + len(somebytes)

    inputfile.close()
    return hexrecords


def read_line(tn):
    # really needs timeout handling
    buf = ""
    buf = tn.readline()
    return buf


def slow_write(tn, outstring):
    for ch in list(outstring):
        if randomerror and (random.randrange(1,400) == 5):
            ch = ' '
        if ch == '\n':
            ch = '\r'
        tn.write(ch)


def transmit_records_reliably(tn, hexrecords):
    slow_write(tn,"\n")

    totlines = len(hexrecords)
    print "\n***",totlines,"records to transmit"

    start = time.time()

    while 1:
        l = read_line(tn)
        try:
            inline = int(l)
        except:
            continue;

        if inline >= totlines:
            slow_write(tn,"65535000"+"\n")
            break

        slow_write(tn,hexrecords[inline] + "\n")
        per = int((1000*inline)/totlines)/10
        sec = time.time() - start
        if sec < 1:
            sec = 1
        bps = int((100*inline * recordwidth) / sec)/100
        print "*", ("% 5d" % inline), hexrecords[inline], " ", per,"% ", bps, "b/s"


if __name__ == '__main__':
    try:
        if (sys.argv[1] == "-h") or (sys.argv[1] == "--help"):
            print "Usage:\n ./vicload decimaldestaddress|0 binaryobject\n"
            exit
        startaddr = int(sys.argv[1]) # TODO: accept leading 0x has hexidecimal
    except:
        exit("first argument: no starting address given (\"-h\" for help)")

    try:
        myfile = sys.argv[2]
    except:
        exit("second argument: no file provided")

    hexrecords = file_to_paperfmt(startaddr,myfile)
    if len(hexrecords) == 0:
        exit("input file: no data to send")

    transmit_records_reliably(ser,hexrecords)

    time.sleep(2)
    ser.close()
